package com.serkol.ams.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.serkol.ams.bean.MyPage;
import com.serkol.ams.entity.*;
import com.serkol.ams.mapper.UsersWalletMapper;
import com.serkol.ams.modal.SqlFeildModal;
import com.serkol.ams.service.*;
import com.serkol.constant.AuthConstant;
import com.serkol.constant.ResultCode;
import com.serkol.exception.AuthException;
import com.serkol.handler.MyLambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pingan
 * @description 针对表【users_wallet】的数据库操作Service实现
 * @createDate 2022-09-23 16:09:15
 */
@Service
public class UsersWalletServiceImpl extends ServiceImpl<UsersWalletMapper, UsersWallet>
        implements UsersWalletService {
    @Autowired
    private UsersService userService;
    @Autowired
    private UsersWalletLogService walletLogService;

    @Autowired
    private UsersWalletIntegralLogService walletIntegralLogService;

    @Autowired
    private UsersWalletWithdrawalService walletWithdrawalService;

    @Autowired
    private NotifyService notifyService;

    @Override
    public boolean reChange(Long parentUserId, BigDecimal price, Integer type) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, parentUserId);
        UsersWalletLog walletLog = new UsersWalletLog();
        walletLog.setOperatorId(loginLog.getUserId());
        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            BigDecimal balance = one.getBalance();
            walletLog.setBalanceOld(balance);
            balance = balance.add(price);
            one.setBalance(balance);

        } else {
            one = new UsersWallet();
            one.setUserId(parentUserId);
            one.setBalance(price);
        }
        boolean b = this.saveOrUpdate(one);
        if (b) {
            walletLog.setBalance(one.getBalance());
            walletLog.setUserId(parentUserId);
            walletLog.setWalletId(one.getId());
            walletLog.setPrice(price);
            walletLog.setType(type);
            walletLog.setState(1);
            walletLogService.save(walletLog);
        }
        return b;
    }

    @Override
    public boolean reChange(Long orderUserId, Long parentUserId, BigDecimal price, Integer type) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, parentUserId);
        UsersWalletLog walletLog = new UsersWalletLog();
        walletLog.setOrderUserId(orderUserId);
        walletLog.setOperatorId(loginLog.getUserId());

        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            BigDecimal balance = one.getBalance();
            walletLog.setBalanceOld(balance);
            balance = balance.add(price);
            one.setBalance(balance);

        } else {
            one = new UsersWallet();
            one.setUserId(parentUserId);
            one.setBalance(price);
        }
        boolean b = this.saveOrUpdate(one);
        if (b) {
            walletLog.setBalance(one.getBalance());
            walletLog.setUserId(parentUserId);
            walletLog.setWalletId(one.getId());
            walletLog.setPrice(price);
            walletLog.setType(type);
            walletLog.setState(1);
            walletLogService.save(walletLog);
        }
        return b;
    }

    @Override
    public boolean reChange(String msg,Long orderId, Long orderUserId, Long parentUserId, BigDecimal price, Integer type) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, parentUserId);
        UsersWalletLog walletLog = new UsersWalletLog();
        walletLog.setOrderUserId(orderUserId);
        walletLog.setOperatorId(loginLog.getUserId());
        walletLog.setOrderId(orderId);
        walletLog.setRemark(msg);
        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            BigDecimal balance = one.getBalance();
            walletLog.setBalanceOld(balance);
            balance = balance.add(price);
            one.setBalance(balance);

        } else {
            one = new UsersWallet();
            one.setUserId(parentUserId);
            one.setBalance(price);
        }
        boolean b = this.saveOrUpdate(one);
        if (b) {
            walletLog.setBalance(one.getBalance());
            walletLog.setUserId(parentUserId);
            walletLog.setWalletId(one.getId());
            walletLog.setPrice(price);
            walletLog.setType(type);
            walletLog.setState(1);
            walletLogService.save(walletLog);
        }
        return b;
    }

    @Override
    public boolean reNoChange(String msg,Long orderId, Long orderUserId, Long parentUserId, BigDecimal price, Integer type)  throws AuthException{
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, parentUserId);
        UsersWalletLog walletLog = new UsersWalletLog();
        walletLog.setOrderUserId(orderUserId);
        walletLog.setUserId(parentUserId);
        walletLog.setOperatorId(loginLog.getUserId());
        walletLog.setRemark(msg);
        walletLog.setPrice(price);
        walletLog.setType(type);
        walletLog.setState(2);
        walletLog.setStatus(1);
        walletLog.setOrderId(orderId);
        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            BigDecimal balance = one.getBalance();

            if(balance.doubleValue()>0) {
                walletLog.setBalanceOld(balance);
                balance = balance.subtract(walletLog.getPrice());
                one.setBalance(balance);
                boolean b = this.saveOrUpdate(one);
                if (b) {
                    walletLog.setWalletId(one.getId());
                    walletLog.setBalance(one.getBalance());
                    walletLog.setState(2);
                    System.out.println(walletLog);
                    walletLogService.save(walletLog);
                }

                return b;
            }else{
                throw new AuthException(ResultCode.REQUEST_ERROR_PAYMENT_REQUIRED, "users.wallet.insufficient.balance");
            }
        } else {
            return false;
        }
    }

    @Override
    public boolean reChange(UsersWalletLog walletLog) {
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, walletLog.getUserId());
        UsersWallet one = this.getOne(queryWrapper);
        System.out.println("Helllo");
        System.out.println(one);
        if (one != null) {
            BigDecimal balance = one.getBalance();
            walletLog.setBalanceOld(balance);
            balance = balance.add(walletLog.getPrice());
            one.setBalance(balance);

        } else {
            one = new UsersWallet();
            one.setUserId(walletLog.getUserId());
            one.setBalance(walletLog.getPrice());
        }
        boolean b = this.saveOrUpdate(one);
        if (b) {
            walletLog.setWalletId(one.getId());
            walletLog.setBalance(one.getBalance());
            walletLogService.save(walletLog);
        }
        return b;
    }

    @Override
    public boolean reNoChange(UsersWalletLog walletLog) throws AuthException {
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, walletLog.getUserId());
        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            BigDecimal balance = one.getBalance();
            if(balance.doubleValue()>0) {
                walletLog.setBalanceOld(balance);
                balance = balance.subtract(walletLog.getPrice());
                one.setBalance(balance);
                boolean b = this.saveOrUpdate(one);
                if (b) {
                    walletLog.setWalletId(one.getId());
                    walletLog.setBalance(one.getBalance());
                    walletLog.setState(2);
                    walletLogService.save(walletLog);
                }

                return b;
            }else{
                throw new AuthException(ResultCode.REQUEST_ERROR_PAYMENT_REQUIRED, "users.wallet.insufficient.balance");
            }
        } else {
            return false;
        }


    }

    @Override
    public boolean reIntegraChange(Long userId, Integer integral) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        UsersWalletIntegralLog walletLog = new UsersWalletIntegralLog();
        walletLog.setOperatorId(loginLog.getUserId());
        queryWrapper.eq(UsersWallet::getUserId, userId);
        UsersWallet one = this.getOne(queryWrapper);
        if (one != null) {
            Integer integrali = one.getIntegral();
            if (integrali == null) {
                integrali = 0;
            }
            walletLog.setIntegralOld(integrali);
            integrali = (integrali + integral);
            one.setIntegral(integrali);

        } else {
            one = new UsersWallet();
            one.setUserId(userId);
            one.setIntegral(integral);
        }
        boolean b = this.saveOrUpdate(one);
        if (b) {
            walletLog.setIntegraln(one.getIntegral());
            walletLog.setUserId(userId);
            walletLog.setWalletId(one.getId());
            walletLog.setIntegral(integral);
            //  walletLog.setType(type);
            walletLog.setState(1);
            walletIntegralLogService.save(walletLog);

        }
        return b;
    }

    @Override
    public boolean reIntegraChange(UsersWalletIntegralLog data) {
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, data.getUserId());
        UsersWallet one = this.getOne(queryWrapper);
        if (data.getState() == 1) {
            if (one != null) {
                Integer integrali = one.getIntegral();
                if (integrali == null) {
                    integrali = 0;
                }
                data.setIntegralOld(integrali);
                integrali = (integrali + data.getIntegral());
                one.setIntegral(integrali);

            } else {
                one = new UsersWallet();
                one.setUserId(data.getUserId());
                one.setIntegral(data.getIntegral());
            }
            boolean b = this.saveOrUpdate(one);
            if (b) {
                data.setIntegraln(one.getIntegral());
                walletIntegralLogService.save(data);
            }
            return b;
        } else {
            if (one != null) {
                Integer integrali = one.getIntegral();
                if (integrali == null) {
                    integrali = 0;
                }
                data.setIntegralOld(integrali);
                integrali = (integrali - data.getIntegral());
                one.setIntegral(integrali);
                boolean b = this.saveOrUpdate(one);
                if (b) {
                    data.setIntegraln(one.getIntegral());
                    walletIntegralLogService.save(data);

                }
                return b;
            } else {
                return false;
            }

        }
    }

    @Override
    public UsersWallet getByUserId(Long userId) {
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, userId);
        UsersWallet byId = this.getOne(queryWrapper);
        return byId;
    }

    @Override
    public Map<String, Object> getInfo() {
        LoginLog loginLog = AuthConstant.getLoginLog();
        LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersWallet::getUserId, loginLog.getUserId());
        UsersWallet one = this.getOne(queryWrapper);
        if (one == null) {
            one = new UsersWallet();
            one.setBalance(BigDecimal.valueOf(0));
            one.setIntegral(0);
        }

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("balance", one.getBalance());
        Integer integral = one.getIntegral();
        if (integral == null) {
            integral = 0;
        }
        map.put("integral", integral);
        map.put("withdrawalWaits", getPrice(2));
        map.put("withdrawal", getPrice(1));

        return map;
    }

    @Override
    public Map<String, Object> getIncomeAndExpenses() {

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("income", getPrice(1, 0));
        map.put("expenses", getPrice(2, 0));

        return map;
    }

    @Override
    public boolean myWithdrawal(UsersWalletWithdrawal data) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        long byWaitByUserCount = walletWithdrawalService.findByWaitByUserCount(loginLog.getUserId());
        if (byWaitByUserCount == 0) {
            LambdaQueryWrapper<UsersWallet> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UsersWallet::getUserId, loginLog.getUserId());
            UsersWallet one = this.getOne(queryWrapper);
            if (one == null) {
                one = new UsersWallet();
                one.setBalance(BigDecimal.valueOf(0));
            }
            data.setBalanceOld(one.getBalance());

            BigDecimal balance = one.getBalance();
            balance = balance.subtract(data.getRequestAmount());
            one.setBalance(balance);
            data.setBalance(balance);
            boolean b = this.saveOrUpdate(one);
            if (b) {
                boolean save = walletWithdrawalService.save(data);
                if (save) {
                    UsersWalletLog walletLog = new UsersWalletLog();
                    walletLog.setUserId(loginLog.getUserId());
                    walletLog.setOrderUserId(loginLog.getUserId());
                    walletLog.setOperatorId(loginLog.getUserId());
                    walletLog.setWalletId(one.getId());
                    walletLog.setPrice(data.getRequestAmount());
                    walletLog.setType(data.getType());
                    // walletLog.setState(data.getStatus());
                    walletLog.setRemark(data.getRemark());
                    walletLog.setState(2);
                    walletLog.setStatus(1);

                    //   int[] a = {2, 3};
                    notifyService.sendMessageUserType(3, walletLog.getUserId(), data.getRemark());
                    boolean save1 = walletLogService.save(walletLog);
                    return save1;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }else {
            return false;
        }

    }


    @Override
    public MyPage<Map<String, Object>> findByPageList(int pageSize, int current, String name, String phone, String parentName, long agentId, String balance) {
        //userService
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(SqlFeildModal.getUsersWalletFullFeild()).lambda().eq(Users::getDeleted,0);

        if (agentId > 0) {
            queryWrapper.lambda().eq(Users::getAgentId, agentId);
        }

        if (StringUtils.isNotEmpty(name)) {
            queryWrapper.lambda().inSql(Users::getId, SqlFeildModal.getAuthNameLike(name));
        }
        if (StringUtils.isNotEmpty(parentName)) {
            queryWrapper.lambda().inSql(Users::getParentUserId, SqlFeildModal.getAuthNameLike(parentName));
        }
        if (StringUtils.isNotEmpty(phone)) {
            queryWrapper.lambda().likeRight(Users::getPhone, phone);
        }
        if (StringUtils.isNotEmpty(balance)) {
          //  queryWrapper.lambda().ge(Users::getBalance, balance);
            if (balance.equals("ascend")) {
                queryWrapper.orderByAsc("balance");
            }else {
                queryWrapper.orderByDesc("balance","ID");
            }
        }else {
            queryWrapper.orderByDesc("ID");
        }

        Page<Map<String, Object>> page = new Page<>(current, pageSize);
        Page<Map<String, Object>> mapPage = userService.getBaseMapper().selectMapsPage(page, queryWrapper);
        return MyPage.parsePage(mapPage);
    }

    @Override
    public Map<String, Object> getInfoLog() {
        Map<String, Object> map = walletWithdrawalService.getInfoLog();
        Map<String, Object> infoWalletLog = getInfoWalletLog();
        map.putAll(infoWalletLog);
        return map;
    }

    @Override
    public Map<String, Object> getUsersStastic() {
        Map<String, Object> map = new HashMap<>();
        MyLambdaQueryWrapper<UsersWallet> queryWrapper = new MyLambdaQueryWrapper<>();
        queryWrapper.sum(UsersWallet::getBalance).as("price").last("LIMIT 1");
        Map<String, Object> map2 = this.getMap(queryWrapper);
        Object price = map2.get("price");
        if (price == null) {
            price = Double.valueOf(0.0);
        }

        map.put("price", price);
        MyLambdaQueryWrapper<UsersWalletLog> queryWrapper1 = new MyLambdaQueryWrapper<>();
        queryWrapper1.sum(UsersWalletLog::getPrice).as("price").last("LIMIT 1");
//WHERE (status NOT IN (2) AND state = 1) GROUP BY name ORDER BY price DESC LIMIT 20
        queryWrapper1.notIn(UsersWalletLog::getStatus, 2).eq(UsersWalletLog::getState, 1);
        Map<String, Object> map1 = walletLogService.getMap(queryWrapper1);
        Object price1 = map1.get("price");
        if (price1 == null) {
            price1 = Double.valueOf(0.0);
        }
        map.put("priceLog", price1);
        return map;
    }


    private Object getPrice(int status) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        QueryWrapper<UsersWalletWithdrawal> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UsersWalletWithdrawal::getUserId, loginLog.getUserId()).eq(UsersWalletWithdrawal::getStatus, status);
        queryWrapper.select("IFNULL(SUM(REQUEST_AMOUNT),0) as price");
        Map<String, Object> map1 = walletWithdrawalService.getMap(queryWrapper);
        Object price = map1.get("price");
        if (price == null) {
            price = Double.valueOf(0.0);
        }

        return price;

    }

    private Object getPrice(int state, int status) {
        LoginLog loginLog = AuthConstant.getLoginLog();
        QueryWrapper<UsersWalletLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UsersWalletLog::getUserId, loginLog.getUserId()).eq(UsersWalletLog::getState, state).eq(UsersWalletLog::getStatus, status);
        queryWrapper.select("IFNULL(SUM(PRICE),0) as price");
        Map<String, Object> map1 = walletLogService.getMap(queryWrapper);
        Object price = map1.get("price");
        if (price == null) {
            price = Double.valueOf(0.0);
        }
        return price;
    }

    private Map<String, Object> getInfoWalletLog() {
        LoginLog loginLog = AuthConstant.getLoginLog();
        Map<String, Object> map = new HashMap<>();
        Date date = DateUtils.addDays(new Date(), -7);
        MyLambdaQueryWrapper<UsersWalletLog> queryWrapper = new MyLambdaQueryWrapper<>();
        queryWrapper.between(UsersWalletLog::getCreateDate, date, new Date());
        //    queryWrapper.sum(UsersWalletLog::getPrice).as("amount");
        queryWrapper.last("limit 1");
        queryWrapper.eq(UsersWalletLog::getUserId, loginLog.getUserId()).eq(UsersWalletLog::getState, 1);
        Long week = walletLogService.count(queryWrapper);

        if (week == null) {
            week = Long.valueOf("0");
        }

        Date date1 = DateUtils.addDays(new Date(), -30);
        MyLambdaQueryWrapper<UsersWalletLog> queryWrapper1 = new MyLambdaQueryWrapper<>();
        queryWrapper1.between(UsersWalletLog::getCreateDate, date1, new Date());

        queryWrapper1.last("limit 1");
        queryWrapper1.eq(UsersWalletLog::getUserId, loginLog.getUserId()).eq(UsersWalletLog::getState, 1);
        Long month = walletLogService.count(queryWrapper1);

        if (month == null) {
            month = Long.valueOf("0");
        }

        map.put("weeks", week);
        map.put("manths", month);

        return map;
    }

}




